/*
 * usart1.c
 *
 *  Created on: 2024年6月25日
 *      Author: 23206
 */


#include "usart1.h"
#include <stdio.h>

//配置串口1的发送跟接收引脚
//USART1_TXD PA9
//USART1_RXD PA10
static void USART1_GPIO_Config(void)
{
	//1.开时钟
	RCC->AHB1ENR |= 1<<0;          // A端口时钟

	GPIOA->MODER &= ~(0x3<<9*2);   //00  浮空模式
	GPIOA->MODER |=  (0x2<<9*2);   //10  复用模式

	GPIOA->MODER &= ~(0x3<<10*2);  //00   浮空模式
	GPIOA->MODER |=  (0x2<<10*2);  //10   复用模式


	GPIOA->OTYPER &= ~(0x1<<9*1);   //		清零
	GPIOA->OTYPER &= ~(0x1<<10*1);  //      清零

    GPIOA->OSPEEDR&= ~(0x3<<9*2);   //		清零
    GPIOA->OSPEEDR&= ~(0x3<<10*2);  //		清零
	GPIOA->OSPEEDR|= (0x3<<9*2);    //11
	GPIOA->OSPEEDR|= (0x3<<10*2);   //11

	GPIOA->PUPDR  &= ~(0x3<<9*2);   //00
	GPIOA->PUPDR  &= ~(0x3<<10*2);  //00

	GPIOA->AFR[1]&= ~(0xF<<4*1);//把AF高位寄存器的891011 设置成0000
	GPIOA->AFR[1]|=  (0x7<<4*1);//把AF高位寄存器的891011 设置从0111

	GPIOA->AFR[1]&= ~(0xF<<4*2);//把AF高位寄存器的891011 设置成0000
	GPIOA->AFR[1]|=  (0x7<<4*2);//把AF高位寄存器的891011 设置从0111

}

//配置串口1的发送跟接收引脚
//USART1_TXD PA2
//USART1_RXD PA3
static void USART2_GPIO_Config(void)
{
	//1.开时钟
	RCC->AHB1ENR |= 1<<0;          // A端口时钟

	GPIOA->MODER &= ~(0x3<<2*2);   //00  浮空模式
	GPIOA->MODER |=  (0x2<<2*2);   //10  复用模式

	GPIOA->MODER &= ~(0x3<<3*2);  //00   浮空模式
	GPIOA->MODER |=  (0x2<<3*2);  //10   复用模式

	GPIOA->OTYPER &= ~(0x1<<2*1);   //		清零
	GPIOA->OTYPER &= ~(0x1<<3*1);  //      清零

    GPIOA->OSPEEDR&= ~(0x3<<2*2);   //		清零
    GPIOA->OSPEEDR&= ~(0x3<<3*2);  //		清零
	GPIOA->OSPEEDR|=  (0x3<<2*2);    //11
	GPIOA->OSPEEDR|=  (0x3<<3*2);   //11

	GPIOA->PUPDR  &= ~(0x3<<2*2);   //00
	GPIOA->PUPDR  &= ~(0x3<<3*2);  //00

	GPIOA->AFR[0]&= ~(0xF<<4*2);//把AF高位寄存器的891011 设置成0000
	GPIOA->AFR[0]|=  (0x7<<4*2);//把AF高位寄存器的891011 设置从0111

	GPIOA->AFR[0]&= ~(0xF<<4*3);//把AF高位寄存器的891011 设置成0000
	GPIOA->AFR[0]|=  (0x7<<4*3);//把AF高位寄存器的891011 设置从0111

}
//初始化串口1 串口参数 波特率 起始位  数据位 校验位 使能位
void USART1_Config(uint32_t bps)
{
	USART1_GPIO_Config();//1.配置IO口GPIO口 复用功能
	RCC->APB2ENR |= 1<<4;//2.配置UART 寄存器
	float USART_DIV ;
	uint32_t DIV_M;
	uint32_t DIV_F;
	uint8_t OVER8;
	USART1->CR1 = 0;//全部清0
    if((USART1->CR1) &(1<<15))//如何判断一个寄存器REG某一位真假
    {
    	OVER8 = 1;
    }
    else
    {
    	OVER8 = 0;
    }
	USART_DIV = 84000000.0/(bps*(8*(2-OVER8))); //bps = 115200
	DIV_M =  USART_DIV;                     //45
	DIV_F = (USART_DIV - DIV_M)*16;         //0.57 * 16 = 1001 = 9
	USART1->BRR = (uint32_t)((DIV_M<<4)|DIV_F);

	// 1.开中断使能位
	USART1->CR1 |= (1<<5);//允许中断  必要条件 但不充分
	USART1->CR1 |= (1<<4);//允许中断  必要条件 但不充分
	// 2.配置中断优先级
	//1.分组
	//2.在这种分组下 编码优先级 1抢占 3次级
	//3.把这个优先级指定给某个中断
	NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(7-2,0,3));
	NVIC_EnableIRQ(USART1_IRQn); //使能某个编号的中断
    // 4.编写中断服务函数
	USART1->CR1 |= (1<<2)|(1<<3)|(1<<13);
}

//初始化串口2 串口参数 波特率 起始位  数据位 校验位 使能位
void USART2_Config(uint32_t bps)
{
	USART2_GPIO_Config();//1.配置IO口GPIO口 复用功能

	RCC->APB1ENR |= 1<<17;//2.配置UART 寄存器

	float USART_DIV ;
	uint32_t DIV_M;
	uint32_t DIV_F;
	uint8_t OVER8;
	USART2->CR1 = 0;//全部清0
    if((USART2->CR1) &(1<<15))//如何判断一个寄存器REG某一位真假
    {
    	OVER8 = 1;
    }
    else
    {
    	OVER8 = 0;
    }
	USART_DIV = 42000000.0/(bps*(8*(2-OVER8))); //bps = 115200
	DIV_M =  USART_DIV;                     //45
	DIV_F = (USART_DIV - DIV_M)*16;         //0.57 * 16 = 1001 = 9
	USART2->BRR = (uint32_t)((DIV_M<<4)|DIV_F);

	// 1.开中断使能位
	USART2->CR1 |= (1<<5);//允许中断  必要条件 但不充分
	USART2->CR1 |= (1<<4);//允许中断  必要条件 但不充分
	// 2.配置中断优先级
	//1.分组
	//2.在这种分组下 编码优先级 1抢占 3次级
	//3.把这个优先级指定给某个中断
//	NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(7-2,1,3));
//	NVIC_EnableIRQ(USART2_IRQn); //使能某个编号的中断


	NVIC_InitTypeDef NVIC_InitStruct;//定义一个结构体变量

	NVIC_InitStruct.NVIC_IRQChannel                   = USART2_IRQn;//通道号
	NVIC_InitStruct.NVIC_IRQChannelCmd                = ENABLE;     //是否使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;          //抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority        = 3;          //次级优先级

	NVIC_Init(&NVIC_InitStruct);//结构体变量的地址




    // 4.编写中断服务函数
	USART2->CR1 |= (1<<2)|(1<<3)|(1<<13);
}
//结构体

USART_Recv_t  USART1_Recv;
void USART1_IRQHandler(void)//PA10接收线
{
	uint8_t data;
	if(USART1->SR & 1<<5)
	{
		USART1->SR &= ~(1<<5);
		data = USART1->DR;
		USART1_Recv.Recv_Buff[USART1_Recv.Recv_Count] = data;
		USART1_Recv.Recv_Count++;
		//printf("U1 %c\r\n",data);//USART1_SendByte PA9 发送线
	}
	if(USART1->SR & 1<<4)
	{
		USART1->DR;
		USART1_Recv.Recv_Buff[USART1_Recv.Recv_Count]='\0';
		USART1_Recv.Recv_Count = 0;//数组下标清0
		USART1_Recv.Recv_Flag  = 1;
	}
}
USART_Recv_t  USART2_Recv;//定义一个结构体变量 开辟空间
void USART2_IRQHandler(void)//PA3接收
{
	uint8_t data;//定义一个局部变量
	if(USART2->SR & 1<<5)
	{
		USART2->SR &= ~(1<<5);
		data = USART2->DR;
		USART2_Recv.Recv_Buff[USART2_Recv.Recv_Count] = data;
		USART2_Recv.Recv_Count++;
		//printf("U2 %c\r\n",data);//USART1_SendByte PA9
	}
	if(USART2->SR & 1<<4)
	{
		USART2->SR;  //读SR 清0
		USART2->DR;  //读DR 清0

		USART2_Recv.Recv_Buff[USART2_Recv.Recv_Count]='\0';
		USART2_Recv.Recv_Count = 0;//数组下标清0
		USART2_Recv.Recv_Flag  = 1;
	}
}

//串口通信 = IO + 串行配置 +中断 、
//发送利用PA9 发送功能Byte-> DR->  TDR -> 移位寄存器 ->PA9 -> CH340_RXD ->PC
//接收利用PC -> CH340_TXD -> PA10 -> RDR -> DR ->recv;
//数据到哪里了  体现SR
//发送字节函数
void USART_SendByte(uint8_t Byte)
{
	while((USART1->SR & 1<<7)==0);//当数据寄存器值未转移到移位寄存器
	USART1->DR  = Byte;//写数据寄存器
}

uint8_t USART_RecvByte(void)
{
	while((USART1->SR & 1<<5)==0);
	return USART1->DR;
}

void USART_SendString(uint8_t *pstr)
{
	while(*pstr!= '\0')//判断指针指向的内容是不是结束 否
	{
		USART_SendByte(*pstr);//打印改字符
		pstr++;  //指针便宜
	}
}

/********************************************/
void USART2_SendByte(uint8_t Byte)
{
	while((USART2->SR & 1<<7)==0);//当数据寄存器值未转移到移位寄存器
	USART2->DR  = Byte;//写数据寄存器
}

void USART2_SendString(uint8_t *pstr)
{
	while(*pstr!= '\0')//判断指针指向的内容是不是结束 否
	{
		USART2_SendByte(*pstr);//打印改字符
		pstr++;  //指针便宜
	}
}
/********************************************/

//接收一个字符 接收到的字符打印
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
	USART_SendByte((uint8_t)ch);
    return ch;
}

//int main(void)
//{
//	KEY_Config();
//	LED_Config();
//	BEEP_Config();
//	USART1_Config(115200);
//	for(uint8_t i = 1;i < 5; i++)
//	{
//		LED_Ctrl(i, 1);
//		USART_SendByte('A');
//		USART_SendByte(0x55);
//		USART_SendByte(0x0D);
//		USART_SendByte(0x0A);
//		//BEEP_Bi(5);
//	}
//	USART_SendString("hello\r\nworld\r\n");
//	printf("HLLO\r\n");
//	printf("%d %c %x\r\n",65,65,65);
//    while(1)
//    {
//
//    }
//}
